﻿using System;
using System.Collections.Generic;
using System.Text;
using Tao.FreeGlut;
using Tao.OpenGl;
using PacMan3D.Utils;
using Tao.DevIl;
using System.IO;
using PacMan3D.Exceptions;
using PacMan3D.Sounds;

namespace PacMan3D.Windows
{
    public enum CurrentImageType { HELP, PLAY, EXIT, LOADING, BACK};

    public class MenuWindow : IWindow
    {
        private int DisplayListId = 0;
        
        private int TexturePlayId = 0;
        private int TextureExitId = 0;
        private int TextureLoadingId = 0;
        private int TextureHelpId = 0;
        private int TextureBackId = 0;

        private CurrentImageType CurrentImage;
        
        public MenuWindow()
        {
            // Image Display List
            this.DisplayListId = Gl.glGenLists(1);
            Gl.glNewList(this.DisplayListId, Gl.GL_COMPILE);
            Gl.glBegin(Gl.GL_QUADS);
            Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex2f(-1.0f, -1.0f);
            Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex2f(1.0f, -1.0f);
            Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex2f(1.0f, 1.0f);
            Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex2f(-1.0f, 1.0f);
            Gl.glEnd();
            Gl.glEndList();

            // Load the Textures
            this.TexturePlayId = ResourceLoader.LoadResource(Constants.RES_TEXT_MENU_PLAY);
            this.TextureExitId = ResourceLoader.LoadResource(Constants.RES_TEXT_MENU_EXIT);
            this.TextureLoadingId = ResourceLoader.LoadResource(Constants.RES_TEXT_MENU_LOADING);
            this.TextureHelpId = ResourceLoader.LoadResource(Constants.RES_TEXT_MENU_INSTRUCTIONS);
            this.TextureBackId = ResourceLoader.LoadResource(Constants.RES_TEXT_MENU_BACK);

            Initialize();

            SoundController.Instance().PlayMusic();
        }

        public void Initialize()
        {
            Glut.glutIgnoreKeyRepeat(1);
            this.CurrentImage = CurrentImageType.PLAY;
        }

        #region IWindow Members

        public void DisplayHandler()
        {
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);

            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();

            Gl.glEnable(Gl.GL_TEXTURE_2D);

            switch (this.CurrentImage)
            {
                case CurrentImageType.PLAY:
                    Gl.glBindTexture(Gl.GL_TEXTURE_2D, this.TexturePlayId );
                    break;

                case CurrentImageType.HELP:
                    Gl.glBindTexture(Gl.GL_TEXTURE_2D, this.TextureHelpId);
                    break;

                case CurrentImageType.EXIT:
                    Gl.glBindTexture(Gl.GL_TEXTURE_2D, this.TextureExitId);
                    break;

                case CurrentImageType.LOADING:
                    Gl.glBindTexture(Gl.GL_TEXTURE_2D, this.TextureLoadingId);
                    break;

                case CurrentImageType.BACK:
                    Gl.glBindTexture(Gl.GL_TEXTURE_2D, this.TextureBackId);
                    break;
            }
            
            Gl.glTexEnvf(Gl.GL_TEXTURE_ENV, Gl.GL_TEXTURE_ENV_MODE, Gl.GL_DECAL);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
            Gl.glCallList(this.DisplayListId);
            Gl.glDisable(Gl.GL_TEXTURE_2D);

            Gl.glFlush();
            Glut.glutSwapBuffers();

            if (this.CurrentImage == CurrentImageType.LOADING)
            {
                Window.Instance().UpdateCurrentMode(Mode.Game);
            }
        }

        public void ReshapeHandler(int width, int height)
        {
            Window.Instance().Width = width;
            Window.Instance().Height = ((height == 0) ? 1 : height);

            Gl.glViewport(0, 0, Window.Instance().Width, Window.Instance().Height);
            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            Glu.gluOrtho2D(-1.0f, 1.0f, -1.0f, 1.0f);

            Glut.glutPostRedisplay();
        }

        public void KeyboardHandler(byte key, int x, int y)
        {
            if (this.CurrentImage == CurrentImageType.LOADING)
                return;

            switch (key)
            {
                // ENTER
                case 13:
                    SoundController.Instance().PlaySound(SoundController.SoundEventType.MENU_ENTER);
                    switch (this.CurrentImage)
                    {
                        case CurrentImageType.HELP:
                            this.CurrentImage = CurrentImageType.BACK;
                            break;

                        case CurrentImageType.EXIT:
                            Window.Instance().ExitGame();
                            break;

                        case CurrentImageType.PLAY:
                            this.CurrentImage = CurrentImageType.LOADING;
                            break;

                        case CurrentImageType.BACK:
                            this.CurrentImage = CurrentImageType.HELP;
                            break;
                    }
                    break;

                // ESC
                case 27:
                    Window.Instance().ExitGame();
                    break;
            }
            Glut.glutPostRedisplay();
        }

        public void SpecialHandler(int key, int x, int y)
        {
            if (this.CurrentImage == CurrentImageType.LOADING
                || this.CurrentImage == CurrentImageType.BACK)
                return;

            SoundController.Instance().PlaySound(SoundController.SoundEventType.MENU_OPTION);

            switch (key)
            {
                case Glut.GLUT_KEY_LEFT:
                    if (this.CurrentImage == CurrentImageType.EXIT)
                        this.CurrentImage = CurrentImageType.PLAY;
                    else if (this.CurrentImage == CurrentImageType.PLAY)
                        this.CurrentImage = CurrentImageType.HELP;
                    break;

                case Glut.GLUT_KEY_RIGHT:
                    if (this.CurrentImage == CurrentImageType.HELP)
                        this.CurrentImage = CurrentImageType.PLAY;
                    else if (this.CurrentImage == CurrentImageType.PLAY)
                        this.CurrentImage = CurrentImageType.EXIT;
                    break;
            }
            Glut.glutPostRedisplay();
        }

        public void IdleHandler() 
        {
        }

        public void SpecialUpHandler(int key, int x, int y) { }

        #endregion

        
    }
}
